package com.enzoism.springboot.dive.chapter02;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author heian
 * @create 2020-01-08-1:55 下午
 * @description 单例自定义线程池，设计参考DefaultThreadFactory
 * @see Executors.DefaultThreadFactory
 * @link https://blog.csdn.net/qq_40826106/article/details/88628536
 */
public final class SingleThreadPool {

    private ExecutorService executors = new ThreadPoolExecutor
            (5, 10, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10), new SingleThreadPool.MyThreadFactory());


    private SingleThreadPool() {
    }

    //返回所需单例类
    public static SingleThreadPool getInstance() {
        return Holder.singleThreadPool;
    }

    //返回单例类所需变量
    public ExecutorService getExecutors() {
        return executors;
    }

    //静态内部类
    private static class Holder {
        private static SingleThreadPool singleThreadPool = new SingleThreadPool();
    }

    //静态内部类
    private static class MyThreadFactory implements ThreadFactory {

        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;//线程名后缀

        MyThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            namePrefix = "myPool-" + poolNumber.getAndIncrement() + "-myThread-";
            //如果这个内部类是外部类，那么每调用一次poolNumber就会+1，目前内部类实际上就固定不变了1
        }

        //线程工厂 制造线程
        public Thread newThread(Runnable r) {
            //线程构造方法
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            //将守护线程设置为非守护线程
            if (t.isDaemon())
                t.setDaemon(false);
            //统一将线程优先级设置为5  默认是5 Thread.NORM_PRIORITY
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

}